package cn.com.wxd.dao.log;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import cn.com.wxd.dao.HibernateDao;
import cn.com.wxd.entity.log.AccesslogInfo;
import cn.com.wxd.entity.log.AccesslogTempInfo;
import cn.com.wxd.entity.log.UserLogInfo;
import cn.com.wxd.common.CharUtil;
import cn.com.wxd.common.DateUtil;
import cn.com.wxd.common.PageInfo;
import cn.com.wxd.common.data.KVMap;

/**
 * Title:AccessLogDaoImpl.java
 * Description:cn.com.wxd.dao.log
 * <p>
 * Company: Amumu管理平台
 * Copyright: Copyright (c) 2015
 * All right reserved.
 * Created time: 2016-4-14 下午4:43:14
 *
 * @author WangXuDong
 * @version 1.0
 */
public class AccessLogDaoImpl extends HibernateDao implements AccessLogDao {
    private static final Logger log = LoggerFactory.getLogger(AccessLogDaoImpl.class);

    @Override
    public int getVisitorVolume() {
        Session session = this.currentSession();
        try {
            // TODO 性能较低的代码，但是比较准确
            //			String sql = "select count(1) from "
            //				+"(select count(1) from log_accesslogs group by left( datetime,10),ip) as aa";
            //			Query query = session.createSQLQuery(sql);
            //			int valume = CharUtil.stringParsInt(query.uniqueResult().toString());
            //			return valume;
            return CharUtil.stringParsInt(session.createCriteria(AccesslogInfo.class)
                    .setProjection(Projections.rowCount())
                    .uniqueResult()
                    .toString());
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return 0;
    }

    @Override
    public int getPvbyAddress(String country, String area, String city) {
        Session session = this.currentSession();
        try {
            Criteria c = session.createCriteria(AccesslogInfo.class);
            if (country != null && !country.equals("")) {
                c.add(Restrictions.ilike("country", country));
            }
            if (area != null && !area.equals("")) {
                c.add(Restrictions.ilike("area", area));
            }
            if (city != null && !city.equals("")) {
                c.add(Restrictions.ilike("city", city));
            }
            c.setProjection(Projections.rowCount());
            int count = CharUtil.stringParsInt(c.uniqueResult().toString());
            return count;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return 0;
    }

    @Override
    public boolean archiveAccessRecode(List<AccesslogInfo> ai) {
        Session session = this.currentSession();
        try {
            for (int i = 0; i < ai.size(); i++) {   //归档
                try {
                    session.save(ai.get(i));
                } catch (Exception e) {
                    if (log.isErrorEnabled()) {
                        log.error("一条用户访问数据插入失败：" + ai.get(i).getRequestUrl()
                                + "--" + ai.get(i).getCountry() +
                                "---" + ai.get(i).getIp() + "--" + ai.get(i).getArea()
                                + "---" + ai.get(i).getCity() +
                                "---" + ai.get(i).getDateTime(), e);
                    }
                }
            }
            session.flush(); //刷入到数据库
            return true;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return false;
    }

    @Override
    public int getPVofToday() {
        Session session = this.currentSession();
        try {
            //性能较低的代码，但是比较准确
            //			String sql = "select count(1) from "
            //				+"(select count(1) from log_accesslogtemp group by left( datetime_temp,10),ip_temp) as aa";
            //			Query query = session.createSQLQuery(sql);
            //			int valume = CharUtil.stringParsInt(query.uniqueResult().toString());
            //			return valume;
            return CharUtil.stringParsInt(session.createCriteria(AccesslogTempInfo.class)
                    .setProjection(Projections.rowCount())
                    .uniqueResult()
                    .toString());
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return 0;
    }

    @Override
    public boolean addAccessRecode(AccesslogTempInfo ati) {
        Session session = this.currentSession();
        try {
            session.save(ati);
            return true;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return false;
    }

    @Override
    public int getAccessRecodeCountByIp(String ip) {
        Session session = this.currentSession();
        try {
            int count = CharUtil.stringParsInt(session.createCriteria(AccesslogTempInfo.class)
                    .add(Restrictions.eq("ip", ip))
                    .setProjection(Projections.rowCount())
                    .uniqueResult()
                    .toString());
            return count;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return 0;
    }

    @Override
    public List<AccesslogTempInfo> selectAccesslogFormTemp() {
        Session session = this.currentSession();
        try {
            List<AccesslogTempInfo> list
                    = (List<AccesslogTempInfo>) session.createCriteria(AccesslogTempInfo.class).list();
            return list;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return null;
    }

    @Override
    public boolean cleanAccesslogTempTable() {
        Session session = this.currentSession();
        try {
            String hql = "DELETE FROM AccesslogTempInfo WHERE 1=1";
            session.createQuery(hql).executeUpdate();
            session.flush();
            return true;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return false;
    }

    @Override
    public boolean insertUserLog(UserLogInfo userLog) {
        Session session = this.currentSession();
        if (userLog == null) {
            return false;
        }
        try {
            session.save(userLog);
            return true;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("用户日志添加失败!", e);
            }
        }
        return false;
    }

    @Override
    public List<UserLogInfo> selectUserLog(int userId, PageInfo page) {
        Session session = this.currentSession();
        List<UserLogInfo> list = null;
        try {
            Criteria c = session.createCriteria(UserLogInfo.class);
            c.add(Restrictions.eq("userId", userId));
            if (page == null) {
                page = new PageInfo();
            }
            c = c.setFirstResult(page.getPageSize() * (page.getPageIndex() - 1))
                    .setMaxResults(page.getPageSize());
            list = (List<UserLogInfo>) c.list();
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
            return null;
        }
        return list;
    }

    @Override
    public List<UserLogInfo> selectUserLog(
            KVMap<String, Object> param, KVMap<String, String> order,
            List<String> fuzzField, PageInfo page) {
        Session session = this.currentSession();
        try {
            List<UserLogInfo> userlogs = null;
            DetachedCriteria dc = DetachedCriteria.forClass(UserLogInfo.class);
            if (param == null) {
                param = new KVMap<String, Object>();
            }
            for (int i = 0; i < param.size(); i++) {
                if (fuzzField != null) {
                    boolean res = false;
                    for (int j = 0; j < fuzzField.size(); j++) {
                        if (param.getKeyIndex(i).equals(fuzzField.get(j))) {
                            res = true;
                            break;
                        }
                    }
                    if (res) {
                        dc.add(Restrictions.ilike(param.getKeyIndex(i)
                                , (String) param.getValueIndex(i), MatchMode.ANYWHERE));
                    } else {
                        dc.add(Restrictions.eq(param.getKeyIndex(i), param.getValueIndex(i)));
                    }
                } else {
                    dc.add(Restrictions.eq(param.getKeyIndex(i), param.getValueIndex(i)));
                }

            }
            Criteria c = dc.getExecutableCriteria(session);
            if (page == null) {
                page = new PageInfo();
            }
            c = c.setFirstResult(page.getPageSize() * (page.getPageIndex() - 1))
                    .setMaxResults(page.getPageSize());
            if (order == null) {
                order = new KVMap<String, String>();
            }
            for (int i = 0; i < order.size(); i++) {
                if (order.getValueIndex(i).equalsIgnoreCase("DESC")) {
                    c.addOrder(Order.desc(order.getKeyIndex(i)));
                } else {
                    c.addOrder(Order.asc(order.getKeyIndex(i)));
                }
            }
            userlogs = (List<UserLogInfo>) c.list();
            return userlogs;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return null;
    }

    @Override
    public List<UserLogInfo> selectUserLogInTimeBuc(int userId,
                                                    String begintime, String endtime, PageInfo page) {
        Session session = this.currentSession();
        List<UserLogInfo> list = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");
        Date startdate = null;
        Date enddate = null;
        try {
            startdate = sdf.parse(begintime);
            enddate = sdf.parse(endtime);
        } catch (ParseException e1) {
            if (log.isErrorEnabled()) {
                log.error("日期格式错误", e1);
            }
            return null;
        }

        try {
            Criteria c = session.createCriteria(UserLogInfo.class);
            c.add(Restrictions.eq("userId", userId));
            c.add(Restrictions.between("idate", startdate, enddate));
            if (page == null) {
                page = new PageInfo();
            }
            c = c.setFirstResult(page.getPageSize() * (page.getPageIndex() - 1))
                    .setMaxResults(page.getPageSize());
            list = (List<UserLogInfo>) c.list();
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
            return null;
        }
        return list;
    }

    @Override
    public int[] selectGroupByDay(int dayNum) {
        Session session = this.currentSession();
        int[] retints = new int[dayNum];
        dayNum--;
        try {
            //			Query query = session.createQuery("select count(1) "
            //					+"from AccesslogInfo as r group by year(cast(r.dateTime as date)),"
            //					+"month(cast(r.dateTime as date)),day(cast(r.dateTime as date)) order by dateTime");
            Query query = session.createSQLQuery("select count(1)  from log_accesslogs" +
                    "  group by SUBSTRING(datetime,1,10) ORDER BY datetime desc");
            query.setMaxResults(dayNum);
            List list = query.list();
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    retints[i + 1] = CharUtil.stringParsInt(String.valueOf(list.get(i)));
                }
            }
            //设置今天的访问量
            int todaycount = CharUtil.stringParsInt(session.createCriteria(AccesslogTempInfo.class)
                    .setProjection(Projections.rowCount())
                    .uniqueResult()
                    .toString());
            retints[0] += todaycount;   //将今天的访问量合并
            return retints;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return null;
    }

    @Override
    public int selectVVByDay(String dateTime) {
        Session session = this.currentSession();
        if (dateTime == null) {
            return 0;
        }
        try {
            Query query = session.createSQLQuery("select count(1) from log_accesslogs " +
                    "where SUBSTRING(datetime,1,10) = '" + dateTime + "'");
            int retint = Integer.parseInt(String.valueOf(query.uniqueResult()));
            if (dateTime.equals(DateUtil.getDateStr())) {  //说明是今天的访问量，这时需要加上未归档的访问数量
                //设置今天的访问量
                int todaycount = CharUtil.stringParsInt(session.createCriteria(AccesslogTempInfo.class)
                        .setProjection(Projections.rowCount())
                        .uniqueResult()
                        .toString());
                retint += todaycount;   //设置今天的访问量
            }
            return retint;
        } catch (Exception e) {
            if (log.isErrorEnabled()) {
                log.error("", e);
            }
        }
        return 0;
    }
}
